// Copyright 2000-2022 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.

package com.lpy.intention;

import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.IncorrectOperationException;
import com.lpy.util.GotoUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * 处理
 * @author Lipengyu
 * @since 2022/05/05 11:06
 */
@NonNls
public class RepositoryToSftlAddSqlId extends PsiElementBaseIntentionAction implements IntentionAction {

    @NotNull
    @Override
    public String getText() {
        return "Generate sql id to the sftl";
    }

    @NotNull
    @Override
    public String getFamilyName() {
        return "JpaExtraX";
    }

    @Override
    public boolean isAvailable(@NotNull Project project, Editor editor, @Nullable PsiElement element) {
        if (element == null) {
            return false;
        }
        if (GotoUtil.isJpaExtraMethod(element.getParent())) {
            return true;
        }
        return false;
    }

    @Override
    public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element)
            throws IncorrectOperationException {
        PsiMethod currentPsiMethod = (PsiMethod) element.getParent();
        String methodName = currentPsiMethod.getName();
        PsiFile psiFile = element.getContainingFile();
        // 当前 Module
        ProjectFileIndex fileIndex = ProjectFileIndex.getInstance(project);
        Module module = fileIndex.getModuleForFile(psiFile.getContainingFile().getVirtualFile());
        if (module == null) {
            return;
        }
        PsiClass currentPsiClass = (PsiClass) currentPsiMethod.getParent();
        String repositoryClassName = currentPsiClass.getName();
        if (GotoUtil.isBlank(repositoryClassName)) {
            return;
        }
        if (!repositoryClassName.contains(GotoUtil.REPOSITORY)) {
            return;
        }
        String entityClassName = GotoUtil.getEntityClassName(currentPsiClass);

        String sqlId = "-- " + methodName;
        // 根据名称查找映射文件

        PsiFile[] entitySftlPsiFiles = FilenameIndex.getFilesByName(project, entityClassName + ".sftl", GlobalSearchScope.moduleScope(module));
        for (PsiFile file : entitySftlPsiFiles) {
            if (GotoUtil.containsSqlId(file, methodName)) {
                GotoUtil.doLocateSftl(project, currentPsiMethod.getName(), file);
                return;
            }
            OpenFileDescriptor descriptor = new OpenFileDescriptor(project, file.getVirtualFile());
            // 打开文件
            Editor sftlEditor = FileEditorManager.getInstance(project)
                    .openTextEditor(descriptor, true);
            if (sftlEditor == null) {
                continue;
            }
            Document document = sftlEditor.getDocument();
            if (document.getText().endsWith("\n")) {
                document.insertString(file.getTextLength(), "\n" + sqlId + "\n");
            } else {
                document.insertString(file.getTextLength(), "\n\n" + sqlId + "\n");
            }
            // 跳转成功，结束该方法
            if (GotoUtil.doLocateLast(project, file)) {
                return;
            }
        }
        // 如果没有找到，则创建新的sftl文件
        if (entitySftlPsiFiles.length == 0) {
            GotoUtil.createFileAndJump(project, module, entityClassName, sqlId);
        }
    }

    @Override
    public boolean startInWriteAction() {
        return true;
    }

}
